package io.wongxd.solution.weight.maskSwitch

import android.animation.ValueAnimator
import android.annotation.SuppressLint
import android.app.Activity
import android.content.Context
import android.graphics.Bitmap
import android.graphics.Canvas
import android.graphics.Paint
import android.graphics.Paint.ANTI_ALIAS_FLAG
import android.graphics.PorterDuff
import android.graphics.PorterDuffXfermode
import android.graphics.Rect
import android.os.Build
import android.os.Handler
import android.os.Looper
import android.view.PixelCopy
import android.view.View
import android.view.ViewGroup
import android.view.Window
import android.view.animation.AccelerateDecelerateInterpolator
import androidx.core.animation.addListener
import kotlin.math.hypot

////xml是通过自定义View实现的，原理就是获取根布局来添加自定义view，自定义view用于动画遮罩和隐藏，所以不用局限在最外层
////直接使用上下文调用activeMaskView来激活自定义View的创建和添加
//context.activeMaskView(
//    animModel = if (isDarkTheme) MaskSwitchAnimModel.SHRINK else MaskSwitchAnimModel.EXPEND,//传入的动画类型
//    clickX = clickX,//动画扩展收缩的圆形的x坐标，可以认为是点击坐标
//    clickY = clickY,//动画扩展收缩的圆形的y坐标，可以认为是点击坐标
//    animTime = 700,//动画时间，单位是毫秒
//    maskComplete = {//遮罩创建完成回调，也就是截图创建绘制完毕准备执行动画之前的回调
//        //....
//    },
//    maskAnimFinish = {//动画结束回调
//       //...
//    },
//)

fun Context.activeMaskView(
    animModel: MaskSwitchAnimModel,
    clickX: Float,
    clickY: Float,
    animTime: Long = 698,
    maskComplete: () -> Unit,
    maskAnimFinish: () -> Unit
) {
    val windows = (this as Activity).window
    val rootView = windows.decorView.rootView as ViewGroup
    captureView(rootView, windows) {
        val bitmap = it
        val maskView = MaskView(animModel, Pair(clickX, clickY), this, bitmap)
        rootView.addView(maskView)
        maskComplete()
        maskView.animActive(animTime) {
            rootView.removeView(maskView)
            maskAnimFinish()
        }
    }
}

private fun View.getScreenshot(): Bitmap {
    val bitmap = Bitmap.createBitmap(this.width, this.height, Bitmap.Config.ARGB_8888)
    val canvas = Canvas(bitmap)
    this.draw(canvas)
    return bitmap
}

private fun captureView(view: View, window: Window, bitmapCallback: (Bitmap) -> Unit) {
    // Above Android O, use PixelCopy
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
        val bitmap = Bitmap.createBitmap(view.width, view.height, Bitmap.Config.ARGB_8888)
        val location = IntArray(2)
        view.getLocationInWindow(location)
        PixelCopy.request(
            window,
            Rect(location[0], location[1], location[0] + view.width, location[1] + view.height),
            bitmap,
            {
                if (it == PixelCopy.SUCCESS) {
                    bitmapCallback.invoke(bitmap)
                }
            },
            Handler(Looper.getMainLooper())
        )
    } else {
        bitmapCallback.invoke(view.getScreenshot())
    }
}

@SuppressLint("ViewConstructor")
private class MaskView(
    private val maskAnimModel: MaskSwitchAnimModel,
    private val clickPosition: Pair<Float, Float> = Pair(0f, 0f),
    context: Context,
    private var bitmap: Bitmap
) : View(context) {
    private var maskRadius = 0f
    private val paint = Paint(ANTI_ALIAS_FLAG)

    @SuppressLint("DrawAllocation")
    override fun onDraw(canvas: Canvas) = with(canvas) {
        val layer = saveLayer(0f, 0f, width.toFloat(), height.toFloat(), null)
        when (maskAnimModel) {
            MaskSwitchAnimModel.EXPEND -> {
                drawBitmap(bitmap, 0f, 0f, null)
                paint.xfermode = PorterDuffXfermode(PorterDuff.Mode.DST_OUT)
                drawCircle(clickPosition.first, clickPosition.second, maskRadius, paint)
            }

            MaskSwitchAnimModel.SHRINK -> {
                drawCircle(clickPosition.first, clickPosition.second, maskRadius, paint)
                paint.xfermode = PorterDuffXfermode(PorterDuff.Mode.SRC_IN)
                drawBitmap(bitmap, 0f, 0f, paint)
            }
        }
        paint.xfermode = null
        restoreToCount(layer)
    }

    fun animActive(animTime: Long, animFinish: () -> Unit) {
        val radiusRange = when (maskAnimModel) {
            MaskSwitchAnimModel.EXPEND -> Pair(
                0f,
                hypot(rootView.width.toFloat(), rootView.height.toFloat())
            )

            MaskSwitchAnimModel.SHRINK -> Pair(
                hypot(rootView.width.toFloat(), rootView.height.toFloat()),
                0f
            )
        }
        ValueAnimator.ofFloat(radiusRange.first, radiusRange.second).apply {
            duration = animTime
            interpolator = AccelerateDecelerateInterpolator()
            addUpdateListener { valueAnimator ->
                maskRadius = valueAnimator.animatedValue as Float
                invalidate()
            }
            addListener(onEnd = {
                animFinish()
            })
        }.start()
    }
}